/*
 * @(#)TaskFigure.java
 *
 * Copyright (c) 1996-2010 by the original authors of JHotDraw and all its
 * contributors. All rights reserved.
 *
 * You may not use, copy or modify this file, except in compliance with the 
 * license agreement you entered into with the copyright holders. For details
 * see accompanying license terms.
 */
package stateDiagram.figures;
import org.jhotdraw.app.action.edit.AbstractSelectionAction;
import org.jhotdraw.app.action.edit.AddInternalTransitionAction;
import org.jhotdraw.app.action.edit.RemoveInternalTransitionAction;
import org.jhotdraw.draw.locator.RelativeLocator;
import org.jhotdraw.draw.handle.MoveHandle;
import org.jhotdraw.draw.handle.Handle;
import org.jhotdraw.draw.layouter.VerticalLayouter;
import org.jhotdraw.draw.connector.LocatorConnector;
import org.jhotdraw.draw.handle.ConnectorHandle;
import java.io.IOException;
import java.awt.Color;

import java.awt.event.ActionEvent;
import java.awt.geom.*;
import static org.jhotdraw.draw.AttributeKeys.*;
import java.util.*;

import javax.swing.Action;
import javax.swing.JButton;

import org.jhotdraw.draw.*;
import org.jhotdraw.draw.handle.BoundsOutlineHandle;
import org.jhotdraw.geom.*;
import org.jhotdraw.util.*;
import org.jhotdraw.xml.*;

import stateDiagram.EntityObjects.Event;
import stateDiagram.EntityObjects.StateEntity;

/**
 * TaskFigure.
 *
 * @author Werner Randelshofer.
 * @version $Id: TaskFigure.java 727 2011-01-09 13:23:59Z rawcoder $
 */
public class StateFigure extends GraphicalCompositeFigure {

	
    /**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	protected HashSet<TransitionFigure> transitions;
	private StateEntity stateEntity;
	
    /** Creates a new instance. */
    public StateFigure() {
        super(new RoundRectangleFigure());
        //addAction(new AddInternalTransitionAction(new JButton()));
        stateEntity = new StateEntity("State","Event","Action");

        setLayouter(new VerticalLayouter());
        RoundRectangleFigure nameCompartmentPF = new RoundRectangleFigure();
        nameCompartmentPF.set(STROKE_COLOR, null);
        nameCompartmentPF.setAttributeEnabled(STROKE_COLOR, false);
        nameCompartmentPF.set(FILL_COLOR, null);
        nameCompartmentPF.setAttributeEnabled(FILL_COLOR, false);
        ListFigure nameCompartment = new ListFigure(nameCompartmentPF);
        ListFigure allEventContainer = new ListFigure();
    	ListFigure exitAttributeCompartment = new ListFigure();
        ListFigure dynamicAttributeCompartment = new ListFigure();
        ListFigure entryAttributeCompartment = new ListFigure();
        SeperatorFigure separator1 = new SeperatorFigure();

        add(nameCompartment);
        add(separator1);
        //add(entryAttributeCompartment);
        add(allEventContainer);
        
        
        Insets2D.Double insets = new Insets2D.Double(20, 20, 20, 20);
        nameCompartment.set(LAYOUT_INSETS, insets);
        //allEventContainer.set(LAYOUT_INSETS, insets);
       // entryAttributeCompartment.set(LAYOUT_INSETS, insets);

        StateNameTextFigure nameFigure;
        nameCompartment.add(nameFigure = new StateNameTextFigure(this.getStateEntity()));
        nameFigure.set(FONT_BOLD, true);
        nameFigure.setAttributeEnabled(FONT_BOLD, false);

        TextFigure EntryEventTextFigure;
        entryAttributeCompartment.add(EntryEventTextFigure = new TextFigure());
        EntryEventTextFigure.setEditable(false);
        EntryEventTextFigure.setText("Entry/");
        EntryEventTextFigure.setAttributeEnabled(FONT_BOLD, false);
        
        EntryActionTextFigure entryActionTextFigure;
        entryAttributeCompartment.add(entryActionTextFigure = new EntryActionTextFigure(this.getStateEntity()));
        entryActionTextFigure.setEditable(true);
        entryActionTextFigure.setText("add Entry action here");
        entryActionTextFigure.setAttributeEnabled(FONT_BOLD, false);
        
        TextFigure exitEventTextFigure;
        exitAttributeCompartment.add(exitEventTextFigure = new TextFigure());
        exitEventTextFigure.setEditable(false);
        exitEventTextFigure.setText("Exit/");
        exitEventTextFigure.setAttributeEnabled(FONT_BOLD, false);
        
        TextFigure exitActionTextFigure;
        exitAttributeCompartment.add(exitActionTextFigure = new ExitActionTextFigure(this.getStateEntity()));
        exitActionTextFigure.setEditable(true);
        exitActionTextFigure.setText("add exit action here");
        exitActionTextFigure.setAttributeEnabled(FONT_BOLD, false);

        setAttributeEnabled(STROKE_DASHES, false);
        
        allEventContainer.add(entryAttributeCompartment);
        allEventContainer.add(dynamicAttributeCompartment);
        allEventContainer.add(exitAttributeCompartment);
        
        ResourceBundleUtil labels =
                ResourceBundleUtil.getBundle("org.jhotdraw.samples.pert.Labels");
        
        // instantiate a new Entity to store this figures data -james
        //need to be able to update entities as user changes labels in figure.
        
        
        stateEntity.setStateFigure(this);
        setName(labels.getString("State"));
        setExit("add exit action");
        setEntry("add entry action");

        transitions = new HashSet<TransitionFigure>();
     
    }
    public StateFigure(Color color) //added by pat to support subclasses 
    {
        super(new RoundRectangleFigure()); //set this color somehow
        set(CANVAS_FILL_COLOR,Color.BLUE);
        set(FILL_COLOR,color);
        stateEntity = new StateEntity("State","Event","Action");

        setLayouter(new VerticalLayouter());
      
       
    }

    @Override
    public Collection<Handle> createHandles(int detailLevel) {
        java.util.List<Handle> handles = new LinkedList<Handle>();
        switch (detailLevel) {
            case -1:
                handles.add(new BoundsOutlineHandle(getPresentationFigure(), false, true));
                break;
            case 0:
                handles.add(new MoveHandle(this, RelativeLocator.northWest()));
                handles.add(new MoveHandle(this, RelativeLocator.northEast()));
                handles.add(new MoveHandle(this, RelativeLocator.southWest()));
                handles.add(new MoveHandle(this, RelativeLocator.southEast()));
                ConnectorHandle ch;
                handles.add(ch = new ConnectorHandle(new LocatorConnector(this, RelativeLocator.east()), new TransitionFigure()));
                handles.add(ch = new ConnectorHandle(new LocatorConnector(this, RelativeLocator.west()), new TransitionFigure()));
                handles.add(ch = new ConnectorHandle(new LocatorConnector(this, RelativeLocator.north()), new TransitionFigure()));
                handles.add(ch = new ConnectorHandle(new LocatorConnector(this, RelativeLocator.south()), new TransitionFigure()));
                ch.setToolTipText("Drag the connector to the next State.");
                break;
        }
        return handles;
    }
    
    public StateEntity getStateEntity() {
		return stateEntity;
	}

	public void setName(String newValue) {
        getNameFigure().setText(newValue);
    }

    public String getName() {
        return getNameFigure().getText();
    }

    public StateNameTextFigure getNameFigure() {
        return (StateNameTextFigure) ((ListFigure) getChild(0)).getChild(0);
    }
    
    public TextFigure getEntryFigure() {
        ListFigure entryfig = (ListFigure) ((ListFigure) getChild(2)).getChild(0);
        return (TextFigure) entryfig.getChild(1);
    }
    
    public void setEntry(String newValue) {
        getEntryFigure().setText(newValue);
    }
    
    public TextFigure getExitFigure() {
      ListFigure ExitFig = getExitContainer();
      return (TextFigure) ExitFig.getChild(1);
       
    }
    
    private ListFigure getExitContainer(){
    	return (ListFigure) ( (ListFigure) getChild(2)).getChild(2);
    }
    
    public void setExit(String newValue) {
        getExitFigure().setText(newValue);
    }
    
    private ListFigure getDynamicContainer(){
    	return (ListFigure) ( (ListFigure) getChild(2)).getChild(1);
    }
    
    
  

    @Override
    public StateFigure clone() {
        StateFigure that = new StateFigure();
     
        that.transitions = new HashSet<TransitionFigure>();
        return that;
    }

    @Override
    public void read(DOMInput in) throws IOException {
        double x = in.getAttribute("x", 0d);
        double y = in.getAttribute("y", 0d);
        double w = in.getAttribute("w", 0d);
        double h = in.getAttribute("h", 0d);
        setBounds(new Point2D.Double(x, y), new Point2D.Double(x + w, y + h));
        readAttributes(in);
        in.openElement("model");
        in.openElement("name");
        setName((String) in.readObject());
        in.closeElement();
        in.closeElement();
        in.openElement("entry");
        getEntryFigure().setText((String) in.readObject());
        in.closeElement();
        in.openElement("exit");
        getExitFigure().setText((String) in.readObject());
        in.closeElement();
        
        
        //internal trans load here
        in.openElement("num");
        int num = (Integer) (in.readObject());
        in.closeElement();
        
        for(int i =0; i < num ; i++){
        	in.openElement("InternalTrans" +i);
        	String e= (String)in.readObject();
        	in.openElement("action");
        	String a = (String)in.readObject();
        	in.closeElement();
        	System.out.println("I am processing internal trans "  + e);
        	addInternalTransition(e, a);
        	in.closeElement();
        }	 
         
    }

    @Override
    public void write(DOMOutput out) throws IOException {
        Rectangle2D.Double r = getBounds();
        out.addAttribute("x", r.x);
        out.addAttribute("y", r.y);
        writeAttributes(out);
        out.openElement("model");
        out.openElement("name");
        out.writeObject(getName());
        out.closeElement();
        out.closeElement();
        out.openElement("entry");
        out.writeObject(getStateEntity().getEntryAction());
        out.closeElement();
        out.openElement("exit");
        out.writeObject(getStateEntity().getExitAction());
        out.closeElement();
        out.openElement("num");
        out.writeObject(getStateEntity().getNumEvents());
        out.closeElement();
        // internal transition save here
        
       ArrayList <Event> events = getStateEntity().getEvents();
       int i =0;
       for (Event e : events){
    	   out.openElement("InternalTrans"+ i);
    	   System.out.println(e.getName());
    	   out.writeObject( e.getName());
    	   out.openElement("action");
    	   out.writeObject(e.getAction());
    	   out.closeElement();
    	   i ++;
    	   out.closeElement();  
       }
       
    
    }

    @Override
    public int getLayer() {
        return 0;
    }

    public Set<TransitionFigure> getDependencies() {
        return Collections.unmodifiableSet(transitions);
    }

    public void addDependency(TransitionFigure f) {
        transitions.add(f);

    }

    public void removeDependency(TransitionFigure f) {
        transitions.remove(f);

    }

    /**
     * Returns dependent StateFigures which are directly connected via a
     * transition to this StateFigure.
     */
    public List<StateFigure> getSuccessors() {
        LinkedList<StateFigure> list = new LinkedList<StateFigure>();
        for (TransitionFigure c : getDependencies()) {
            if (c.getStartFigure() == this) {
                list.add((StateFigure) c.getEndFigure());
            }

        }
        return list;
    }

    /**
     * Returns predecessor StateFigures which are directly connected via a
     * transition to this StateFigure.
     */
    public List<StateFigure> getPredecessors() {
        LinkedList<StateFigure> list = new LinkedList<StateFigure>();
        for (TransitionFigure c : getDependencies()) {
            if (c.getEndFigure() == this && c.getStartFigure() instanceof StateFigure) {
                list.add((StateFigure) c.getStartFigure());
            }

        }
        return list;
    }

    /**
     * Returns true, if the current task is a direct or
     * indirect dependent of the specified task.
     * If the dependency is cyclic, then this method returns true
     * if <code>this</code> is passed as a parameter and for every other
     * task in the cycle.
     */
    public boolean isDependentOf(StateFigure t) {
        if (this == t) {
            return true;
        }

        for (StateFigure pre : getPredecessors()) {
            if (pre.isDependentOf(t)) {
                return true;
            }

        }
        return false;
    }
    
  

    @Override
    public String toString() {
        return ("TaskFigure#" + hashCode() + " " + getName() + " " );
    }
    //override getActions()-james
    public Collection<Action> getActions(Point2D.Double p) {
    	Collection<Action> popupMenu = new ArrayList<Action>();
    	  popupMenu.add(new AddInternalTransitionAction(null, this));
    	  
    	 
    	int index = getDynamicContainer().findChildIndex(p); 
    	if (index != -1){
    		popupMenu.add(new RemoveInternalTransitionAction(null, this, index));
    	}
    return popupMenu;
    }
    
    
    public void addInternalTransition(String eventName, String actionName ){
    	 willChange();
         getDynamicContainer().add(new InternalTransitionFigure(eventName, actionName, getStateEntity()));
    	 changed();	
    }
    
    public void removeInternalTransition(int index){
    	System.out.println("I got called");
    	willChange();
    	getDynamicContainer().basicRemoveChild(index);
    	changed();	
    }
    
}

